<?php
declare (strict_types=1);

namespace app\exam\service\admin;

use app\admin\logic\system\Config as SystemConfig;
use app\common\exception\LogicException;
use app\common\helper\util\Tool;
use app\common\logic\category\admin\Category;
use app\common\service\BaseService;
use app\exam\logic\admin\Paper as PaperLogic;
use app\user\model\teacher\admin\Teacher;
use eduline\admin\libs\pageform\FormItem;
use eduline\admin\libs\pagelist\ListItem;
use eduline\admin\page\PageForm;
use eduline\admin\page\PageList;
use PhpOffice\PhpWord\Element\Section;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\SimpleType\Jc;
use think\annotation\Inject;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Request;
use think\Response;

/**
 * Class Paper
 *
 * @package app\exam\service\admin
 */
class Paper extends BaseService
{

    /**
     * @Inject()
     *
     * @var PaperLogic
     */
    protected $paperLogic;

    /**
     * @Inject()
     *
     * @var Category
     */
    protected $category;

    /**
     * index
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/1/23
     *
     * @throws DbException
     */
    public function index(): Response
    {
        $map = [];
        // 关键字
        Request::has('title', 'get', true) && $map[] = ['title', 'like', '%' . Request::get('title/s') . '%'];
        // 试卷类型
        if (Request::has('paper_type', 'get', true) && Request::get('paper_type/d', -1) !== -1) {
            $map[] = ['paper_type', '=', Request::get('paper_type/d')];
        }
        // 分类
        $category = Request::get('category/s', 0);
        $category && $map[] = ['category', 'Like', '%,' . $category . ','];

        $data = $this->paperLogic->getList($map)->append(['category_str', 'paper_type_text', 'total_time_text', 'exam_number_text']);
        // 定义字段
        $keyList   = [
            'title'            => ListItem::make()->title('试卷名称'),
            'category_str'     => ListItem::make()->title('试卷分类'),
            'paper_type_text'  => ListItem::make()->title('试卷类型'),
            'total_count'      => ListItem::make()->title('总题数'),
            'total_score'      => ListItem::make()->title('总分数'),
            'total_time_text'  => ListItem::make()->title('作答时长'),
            'exam_number_text' => ListItem::make()->title('考试次数'),
            // 'status'           => ListItem::make('custom')->title('发布状态'),
            'update_time'      => ListItem::make()->title('更新时间')
        ];
        $category  = $this->category->cascader(0, 3);
        $paperType = $this->paperLogic->getPaperTypeOptions();
        // 搜索字段
        $searchKey = [
            'paper_type' => FormItem::make('select')->title(false)->placeholder('试卷类型')->options($paperType),
            'category'   => FormItem::make('cascader')->title(false)->placeholder('试卷分类')->options($category),
            'title'      => FormItem::make()->title(false)->placeholder('试卷名称')->maxlength(30),
        ];

        // 设置表单
        $list = new PageList();
        // 表单字段
        $list->pageKey   = $keyList;
        $list->datas     = $data;
        $list->searchKey = $searchKey;

        return $list->send();
    }

    /**
     * 试卷配置
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 23/03/16
     */
    public function config(): Response
    {
        $keyList = [
            'number' => FormItem::make('inputNumber')->title('切屏次数')->min(0)->max(10)->help('超过配置将自动交卷，最高配置10次'),
        ];

        $form = new PageForm;
        // 表单字段
        $form->pageKey = $keyList;
        $form->withSystemConfig();
        $key             = 'exam.paper.config';
        $config          = SystemConfig::get($key, ['number' => 0], request()->mhm_id);
        $config['__key'] = $key;

        $form->datas = $config;

        return $form->send();
    }

    /**
     * 新建试卷页面数据
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/21
     *
     *
     */
    public function create(): Response
    {
        $datas = [
            'category' => $this->category->cascader(0, 3),
            'mhm_id'   => request()->mhm_id
        ];

        return static::parseToData($datas, 1);
    }

    /**
     * 新建固定试卷
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/21
     */
    public function createSettled(): Response
    {
        $data = Request::post();
        $this->paperLogic->createPaper($data);

        return static::parseToData([], 1, '新建成功');
    }

    /**
     * 编辑固定试卷
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/22
     *
     * @param int $id
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function editSettled(int $id): Response
    {
        if (Request::isPut()) {
            $data = Request::put();
            $this->paperLogic->editPaper($id, $data);

            return static::parseToData([], 1, '编辑成功');
        }

        return $this->extracted($id);
    }

    /**
     * 新建随机试卷
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/21
     */
    public function createRandom(): Response
    {
        $data = Request::post();
        $this->paperLogic->createPaper($data, 2);

        return static::parseToData([], 1, '新建成功');
    }

    /**
     * 编辑固定试卷
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/22
     *
     * @param int $id
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function editRandom(int $id): Response
    {
        if (Request::isPut()) {
            $data = Request::put();
            $this->paperLogic->editPaper($id, $data, 2);

            return static::parseToData([], 1, '编辑成功');
        }

        return $this->extracted($id);
    }

    /**
     * 获取试卷详情
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/2/8
     *
     * @param int $id
     *
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function info(int $id): Response
    {
        $paperInfo = $this->paperLogic->getPaperInfo($id);

        return static::parseToData($paperInfo, 1);
    }

    /**
     * 单个删除
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/21
     *
     * @param int $id
     * @return Response
     */
    public function delete(int $id): Response
    {
        $this->paperLogic->deletePapers($id);

        return static::parseToData([], 1, '删除成功');
    }

    /**
     * 批量删除
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/12/21
     *
     * @param string $ids
     * @return Response
     */
    public function deletes(string $ids): Response
    {
        $this->paperLogic->deletePapers($ids);

        return static::parseToData([], 1, '删除成功');
    }

    /**
     * 编辑单个字段信息
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/3/10
     *
     * @param int    $id
     * @param string $field
     * @return Response
     */
    public function editField(int $id, string $field): Response
    {
        $value  = Request::put($field);
        $module = $this->paperLogic->editField($id, $field, $value);

        return BaseService::parseToData($module, 1, '更新成功');
    }

    /**
     * 导出试卷
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/3/31
     *
     * @param int $id
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function export(int $id)
    {
        $paperInfo = $this->paperLogic->getPaperInfo($id);
        if ($paperInfo['paper_type'] != 1) {
            throw new LogicException('暂不支持导出随机卷');
        }
        $word = new PhpWord();
        // 全局行间距
        $word->setDefaultParagraphStyle([
            'spacing' => 150
        ]);
        $section = $word->addSection();
        // 试卷名称
        $titleBox = $section->addTextRun([
            'align' => Jc::CENTER
        ]);
        $titleBox->addText($paperInfo['title'], [
            'size'  => 22,
            'bold'  => true,
            'color' => '#303133',
        ]);
        $descriptionStyle = ['size' => 12, 'color' => '#606266'];
        // 试卷简介
        if ($paperInfo['info']) {
            $paperDescription = $section->addTextRun([
                'align' => Jc::CENTER
            ]);
            $paperDescription->addText($paperInfo['info'], $descriptionStyle);
        }
        // 试卷总分
        $metaBox = $section->addTextRun([
            'align' => Jc::CENTER
        ]);
        $metaBox->addText('试卷总分：' . $paperInfo['total_score'] . ' 分', $descriptionStyle);
        // 试卷作答时长
        if ($paperInfo['total_time'] != 0) {
            $metaBox->addText('    作答时长：' . $paperInfo['total_time'] . ' 分钟', $descriptionStyle);
        }
        // 填充2个换行
        $section->addTextBreak(2);
        // 部分名称样式
        $partTitleStyle = ['bold' => true, 'size' => 20, 'color' => '#303133'];
        // 部分说明样式
        $partDescStyle = ['size' => 12, 'color' => '#606266'];
        // 数据输出
        foreach ($paperInfo['paper_parts'] as $part) {
            // 部分
            $text = $section->addTextRun();
            // 部分标题与题目数量
            $text->addText($part['title'] ?: '第' . Tool::number2chinese($part['number']) . '部分', $partTitleStyle);
            $text->addText(' 共计 ' . count($part['value']) . ' 道题', $partDescStyle);
            // 是有有部分说明
            $part['description'] && $text->addText('（' . $part['description'] . '）', $partDescStyle);
            // 试题
            foreach ($part['value'] as $number => $valueItem) {
                $topic = $valueItem['topic'];
                $this->parseExportTopic($section, $topic, $number + 1);
            }
            // 每部分结束后空一行
            $section->addTextBreak();
        }

        $word->save(urlencode($paperInfo['title'] . '.docx'), 'Word2007', true);
    }

    /**
     * 解析导出的试题数据
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/3/31
     *
     * @param       $section Section
     * @param       $topic
     * @param       $number
     * @param false $isSub
     */
    protected function parseExportTopic($section, $topic, $number, $isSub = false)
    {
        $suffix = $isSub ? '（' . $number . '）.' : $number . '、';
        // 试题样式
        $topicStyle = ['size' => 14, 'color' => '#303133'];
        // 题干
        $title = $section->addTextRun();
        $title->addText($suffix . '【' . $topic['question_type_text'] . '题】', $topicStyle);
        $title->addText(Tool::filterHtml($topic['title']), $topicStyle);
        $this->handleImages($section, $topic['title']);
        switch ($topic['question_type']) {
            case 6:// 材料题
            case 7:// 完型填空
                // 小题
                foreach ($topic['options'] as $index => $subTopic) {
                    $this->parseExportTopic($section, $subTopic, $index + 1, true);
                }
                break;
            case 5:// 填空题,只要题干,无需其他内容
                break;
            case 8:// 简答题,添加2行,用于填写答案
                $section->addTextBreak(2);
                break;
            default:
                // 选项
                foreach ($topic['options'] as $option) {
                    $options = $section->addTextRun();
                    $options->addText($option['key'] . '. ' . Tool::filterHtml($option['value']), $topicStyle);
                    $this->handleImages($section, $option['value']);
                }
                break;
        }
        $section->addTextBreak();
    }

    /**
     * handleImages
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2021/4/1
     *
     * @param $section Section
     * @param $string
     */
    protected function handleImages($section, $string)
    {
        // 匹配图片
        $images = Tool::getImagesFromHtml($string);
        if ($images) {
            foreach ($images as $image) {
                $section->addImage($image);
            }
        }
    }

    /**
     * extracted
     * Author: 亓官雨树 <lucky.max@foxmail.com>
     * Date: 23/03/16
     *
     * @param int $id
     *
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected function extracted(int $id): Response
    {
        $paperInfo = $this->paperLogic->getPaperInfo($id);
        if ($paperInfo['reviewer']) {
            $paperInfo['teacher_name'] = Teacher::withTrashed()->with(['user'])->where('id', $paperInfo['reviewer'])->findOrEmpty()->getAttr('teacher_name');
        }
        $category = $this->category->cascader(0, 3);

        return static::parseToData([
            'paper_info' => $paperInfo,
            'category'   => $category
        ], 1);
    }

    /**
     * 获取试卷基础信息
     *
     * @param int $id
     * @return Response
     */
    public function baseInfo(int $id)
    {
        $paperBaseInfo = $this->paperLogic->getPaperBaseInfo($id);

        return static::parseToData($paperBaseInfo->toArray(), 1);
    }
}
